<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
<script>
    在ES6中使用{}时,
        若果key和val长的一样
        原来必须使用
        {
            key:val.
            key:val
        }
        可以进化为
        {
            key
            key
        }

    在对象中的函数
        {
            fn:function () {
                alert(1);
            }
        }
        可以进化为
        {
            fn(){
                alert(1);
            }
        }


    面向对象写法
        class Person{
            constructor(name,age){
                this.name = name;
                this.age = age;
            }
            say(){
                alert(this.name);
            }
        }
        如果用class的方法写了类,那么类的 prototype 不能改写

        extends继承：
            class Police extends Person{
                constructor(name,age){
                    super(name,age)
                }
                kungfu(){
                    alert('一阳指，九阴白骨爪')
                }
            }
            class 子类 extends 父类{
                constructor(父类参数,自己的){
                    super(父类参数)
                    自己的
                }
                自己的方法(){

                }
            }


    箭头函数
        以前的函数
            function fn() {
                alert(1);
            }
        ES6的函数
            表达式
            var fn = () => 5; 申明了一个函数  return了5,适用于一行代码，不传参的时候()必须加
            var fn = () =>{  申明了一个函数，执行括号中的代码，适用于多行代码
               var a = 1+1;
               var b = a+2;
               alert(b);
             }
             var fn = (a) => a
             var fn = a => a  在一个参数的时候，可以省略传参中的括号
             var fn = (a,b) => {} 如果有多个参数，()不能省略
        箭头函数的this永远指向定义父级,全局事件绑定不要用箭头函数,箭头函数不能new,不然报错


    变量,常亮,块
        变量:var
            let
                1.不会走预解析,在没有声明前使用会报错
                2.使用let不会再window下注册一个属性
                3.使用let变量名不允许是重复的,如果重复,就报错
                4.let在for循环中可以替代索引
        常量:const
            1.赋值后不会被改变,而且定义时就必须赋值,不赋值就会报错
            2.其他和let相同
            3.某些名只会使用,不会被改变,就用const
        块:{} 一个块就相当于一个作用域,子级能访问父级域中的变量/常量，而父级不能访问子级的变量/常量


    解构赋值:
        需求:var a = 10;
            var b = 20;
            如果要想让a,b互换
        解决:
            var [b,a] = [a,b];

        对象解构 {}
            会找到对象名字替换
            var {a:e,b:f} = {a:1,b:2}
            e => 1, b => 2
            会把a和b的value值拿过来赋值给e和f


    Number.isNaN()
        和isNaN()的区别:
            isNaN()内部会调用Number方法
            Number.isNaN()内部不会调用Number方法,只会看参数是不是NaN


    Math.trunc(num)
        抹去num的小数


    扩展运算符  ...
        扩展运算符用三个点号表示，功能是把数组或类数组对象展开成一系列用逗号隔开的值
        把数组每个都拆出来
        var arr = [1, 2, 3];
        //传统写法
        foo(arr[0], arr[1], arr[2]); => 1,2,3
        //使用扩展运算符
        foo(...arr);   =>  1,2,3
        var str = '1234567';
        var arr = [...str]  =>  ['1','2','3','4','5','6','7']


    数组去重
        set中不允许有重复项
        var  arr = [1,2,2,2,2,3,4,5,6,7,8,7,6,5,4,7,8,3,1,5]
        var arr2 = [...new Set(arr)];


    Array.of()
        将一组值转成数组
        Array.of(1,2,3,4,5) => [1,2,3,4,5]


    Object.keys(obj)
        keys方法可以获取对象中的key值，并把他们放入数组，这样可以知道对象的长度


    给obj加for of循环方法(遍历器)
        var obj = {name:'小红',age:2,sex:'女'};
        obj[Symbol.iterator] = function () {
            let arr = Object.keys(obj);
            let i = 0;
            let len = arr.length;
            return{
                next(){
                    if(i < len){
                        return{
                            value:{
                                val:obj[arr[i]],
                                key:arr[i++],
                            },
                            done:false,
                        }
                    }else{
                        return{
                            value:null,
                            done:true,
                        }
                    }
                }
            }
        }
        for(var {val,key} of obj){
            console.log(val,key); => key:name val:'小红'
        }


    函数暂停实行方法: (Generator 函数)
        function *fn(){
            yield 'hello';
            yield '事件';
            return '呵呵哒'
        }
        fn();  调用之后不会执行
        fn().next(); 只有使用next调用后,才会执行，遇到yield暂停,会返回遍历器中return值
        第一次调用 => hello;
        第二次调用 => 事件;
        第三次调用 => 呵呵哒;
        第四次调用 => undefined;


    Promise 解决异步问题
        有两个特点:
        第一个:
            Promise对象代表一个异步操作,有三种状态
            Pending(进行中)
            Resolved(已完成)
            Rejected(已失败)
        第二个:一旦状态改变，就不会再变
        例子：E:\（5）miaov\js高级\2017-5-3-class\2017-7-28\8_Promise.html


    ES6模块化
        !!!浏览器不支持!!! 通过babel去转一下
        使用webpack将es6的语法转成es5，开发的时候既可以使用ES6的新语法又能在浏览器下正常运行
        webpack又是基于Node环境的,所以要安装Node
        export  输出
            可输出变量，函数，类，输出时必须使用{}，使用as可以改变变量输出时的名字
            var n = 1;
            export {n as m};
        import  导入
            接收export输出的模块的值，导入的时候必须加{}
            import {firstName, lastName, year} from './profile';
            解构赋值    输出的对象名                模块化js的路径 ./代表当前路径

        export default function () {  一般使用default输出匿名函数
            console.log('foo')
        }
        import a from './export-default'  如果使用default输出，导入时则不需要加{}，变量可以随便起

    Object.assgin

    在定义类式，必须传入的属性使用形参直接传入，可选属性使用对象传入

    深拷贝异步回调
    function deepClone(obj) {
      return new Promise((re,rj)=>{
        var {port1,port2} = new MessageChannel();
      port2.onmessage = ev => re(ev.data);
      port1.postMessage(obj);
      })
    }
</script>
</html>
